/*
 * containerstore.h
 *
 *  Created on: Nov 11, 2013
 *      Author: fumin
 */

#ifndef CONTAINERSTORE_H_
#define CONTAINERSTORE_H_

#include "../destor.h"

#define CONTAINER_SIZE (4194304ll)	  // 4MB
#define CONTAINER_META_SIZE (65536ll) // 64KB

/* CONTAINER_HEAD includes three elenents: containerid(8B), data_size(4B) and chunk_num(4B) */
#define CONTAINER_HEAD 16
/* including the meta entry, each of which size of 53 bytes */
#define CONTAINER_META_ENTRY 53

struct containerMeta
{
	containerid id;
	int32_t data_size;
	int32_t chunk_num;

	/* Map fingerprints to chunk offsets. */
	GHashTable *map;
	GHashTable *delta_sf1;
	GHashTable *delta_sf2;
	GHashTable *delta_sf3;
	struct metaEntry *head;
	struct metaEntry *tail;
};

/*
 * Container is fixed-sized structure (4MB).
 * It consists of two portions: metadata and data portions.
 * All chunks are sequentially written to the data portions,
 * and are indexed by the metadata portion.
 *
 * The metadata portion consists of two parts:
 * 1) the head: describing the container.
 * 3) the meta entries
 */
struct container
{
	struct containerMeta meta;
	unsigned char *data;
};

void init_container_store();
void close_container_store();

struct container *create_container();
struct container *create_sparse_base_container();

void write_container(struct container *);
void write_container_async(struct container *);
struct container *retrieve_container_by_id(containerid);
struct containerMeta *retrieve_container_meta_by_id(containerid);
struct containerMeta *retrieve_container_meta_by_id_async(containerid);
struct container *container_duplicate(struct container *);
struct index_item *retrieve_fp_and_id(struct containerMeta *cm, struct chunk *ck);

struct container *retrieve_container_in_write_buffer(containerid id);

struct chunk *get_chunk_in_container(struct container *, fingerprint *);
struct chunk *get_basechunk_in_container(struct container *, fingerprint *);
int add_chunk_to_container(struct container *, struct chunk *);
int container_overflow(struct container *, struct chunk *);
void free_container(struct container *);
void free_container_meta(struct containerMeta *);
containerid get_container_id(struct container *c);
int container_empty(struct container *c);

gint g_container_cmp_desc(struct container *, struct container *, gpointer);
gint g_container_meta_cmp_desc(struct containerMeta *, struct containerMeta *,
							   gpointer);

int lookup_fingerprint_in_container(struct container *, fingerprint *);
int lookup_fingerprint_in_container_meta(struct containerMeta *, fingerprint *);
int lookup_sf_in_container_meta(struct containerMeta *cm,
								struct chunk *ck);
int lookup_chunk_in_container(struct container *c, struct chunk *ck);
int container_check_id(struct container *, containerid *);
int container_meta_check_id(struct containerMeta *, containerid *);

void container_meta_foreach(struct containerMeta *cm, void (*func)(fingerprint *, void *), void *data);

int64_t get_container_count();
#endif /* CONTAINERSTORE_H_ */
